//============================================================================================
/**
 * @file	jump_ai.c
 * @brief	ジャンプAI
 * @author	Nozomu Saito
 *
 * モジュール名：JumpAI_
 */
//============================================================================================

#include "jump_ai.h"
#include "jump_comm.h"

#define EXE_FRAME_ALONE	(3)			//非通信時AI実行フレーム間隔
#define EXE_FRAME_COMM	(3)			//通信時AI実行フレーム間隔

#define POINTGET_GRADING		(100)

typedef struct JUMP_AI_CNT_tag
{
	BOOL Execute;
	COMM_EVENT_COMMON_DATA *CommData;
	u8 JumpTotal[ENTRY_MEMBER_NUM_MAX];
	u8 TechniqueTotal[ENTRY_MEMBER_NUM_MAX];
	u8 Prob[ENTRY_MEMBER_NUM_MAX][ENTRY_MAX];

	u8 NpcNum;	//0〜3
	u8 ExeNpcIdx;	//0〜2
	u8 Frame;
	u8 CntFrame;
	u8 NpcStartIdx;	//1〜3
	u8 PlayerNum;	//1〜4
	u8 dummy[2];
}JUMP_AI_CNT;

static void ExecuteAI(PKTHLN_PTR work, JUMP_AI_CNT_PTR ptr, const u8  inTarget);

//----------------------------------------------------------------------------
/**
 *	@brief	初期化
 *
 *	@param	inHeapID		ヒープID
 *	@param	inNpcNum		NPCの数
 *	@param	inType			ゲームタイプ（通信してるか）
 *	@param	data			通信データ
 *	@param	work			ポケスロンポインタ
 *
 *	@return ptr				コントロールポインタ
 */
//-----------------------------------------------------------------------------
JUMP_AI_CNT_PTR JumpAI_Init(const int inHeapID, const int inNpcNum,
							const PKTHLN_GAME_TYPE inType,
							COMM_EVENT_COMMON_DATA *data,
							PKTHLN_PTR work )
{
	int i;
	JUMP_AI_CNT_PTR cnt_ptr;
	//メモリアロケーション
	int size = sizeof(JUMP_AI_CNT);
	cnt_ptr = sys_AllocMemory(inHeapID, size);
	MI_CpuClear8( cnt_ptr, size);

	cnt_ptr->NpcNum = inNpcNum;
	cnt_ptr->PlayerNum = ENTRY_MEMBER_NUM_MAX-inNpcNum;
	cnt_ptr->NpcStartIdx = cnt_ptr->PlayerNum;
	if (inType == PKTHLN_GAME_ALONE){
		cnt_ptr->CntFrame = EXE_FRAME_ALONE;
	}else{
		cnt_ptr->CntFrame = EXE_FRAME_COMM;
	}
	cnt_ptr->CommData = data;

	//ポケモンパラメータ
	for (i=0;i<cnt_ptr->NpcNum;i++){
		u8 net_id;
		int j;
		const POKE_SPEC *spec;
		net_id = cnt_ptr->NpcStartIdx + i;
		for (j=0;j<ENTRY_MAX;j++){
			spec = PTFrame_GetPokeSpec(work, net_id, j);
			cnt_ptr->JumpTotal[net_id] += spec->Jump;
			cnt_ptr->TechniqueTotal[net_id] += spec->Technique;
			cnt_ptr->Prob[net_id][j] = cnt_ptr->JumpTotal[net_id];
		}
	}

	return cnt_ptr;
}

//----------------------------------------------------------------------------
/**
 *	@brief	解放
 *
 *	@param	ptr				コントロールポインタ
 *
 *	@return none
 */
//-----------------------------------------------------------------------------
void JumpAI_End(JUMP_AI_CNT_PTR ptr)
{
	//メモリ解放
	sys_FreeMemoryEz(ptr);
}

//----------------------------------------------------------------------------
/**
 *	@brief	ＡＩ実行
 *
 *  @param	work		ポケスロンワーク
 *	@param	ptr			管理ポインタ
 *
 *	@return u8		動かしたＮＰＣインデックス
 */
//-----------------------------------------------------------------------------
u8 JumpAI_Execute(PKTHLN_PTR work, JUMP_AI_CNT_PTR ptr)
{
	int i;
	u8 exe_idx;
	exe_idx = ENTRY_MEMBER_NUM_MAX;

	if (ptr->PlayerNum == ENTRY_MEMBER_NUM_MAX){
		//AIなし
		return 0;
	}

	ptr->Frame++;

	//得点取得フラグは毎回落としておく
	for(i=ptr->NpcStartIdx;i<ENTRY_MEMBER_NUM_MAX;i++){
		JUMP_CHILD_DATA *child_rec;
		child_rec = PKTHLN_CommPack_GetData(&ptr->CommData->ReciveData[i]);
		child_rec->PointGet = 0;
	}

	if (ptr->Frame >= ptr->CntFrame){
		//実行状態にする
		ptr->Execute = TRUE;
		ptr->Frame = 0;
	}

	if (ptr->Execute){	//実行状態
		int exe_npc;
		//実行NPCの決定
		exe_npc = ptr->NpcStartIdx + ptr->ExeNpcIdx;
		GF_ASSERT(exe_npc >= ptr->NpcStartIdx );
		if (exe_npc < ptr->NpcStartIdx){		//このif条件は絶対に満たされないが、保険のため
			return exe_idx;
		}
		//実行
		ExecuteAI(work, ptr, exe_npc);
		exe_idx = exe_npc;
		//実行NPCのシフト
		ptr->ExeNpcIdx++;
		if (ptr->ExeNpcIdx >= ptr->NpcNum){	//シフト後一巡したら、
			ptr->ExeNpcIdx = 0;
			//実行フラグを落とす
			ptr->Execute = FALSE;
		}
	}
	return exe_idx;
}

//----------------------------------------------------------------------------
/**
 *	@brief		AI実行
 *
 *	@param	work			ポケスロンワーク
 *	@param	ptr				コントローラポインタ
 *	@param	inTarget		対象NPCインデックス
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ExecuteAI(PKTHLN_PTR work, JUMP_AI_CNT_PTR ptr, const u8  inTarget)
{
	int grading;
	JUMP_CHILD_DATA *child_rec;
	child_rec = PKTHLN_CommPack_GetData(&ptr->CommData->ReciveData[inTarget]);

	//得点取得評価
	if (ptr->JumpTotal[inTarget] == 0){
		grading = 0;
	}else{
		grading = ptr->JumpTotal[inTarget]*2 + ptr->TechniqueTotal[inTarget] + ( gf_rand()%101 );
	}

	if (grading >= POINTGET_GRADING){
		u8 i;
		u8 prob;
		//得点取得
		child_rec->PointGet = 1;
		prob = gf_rand()%ptr->JumpTotal[inTarget];
		for (i=0;i<ENTRY_MAX;i++){
			if (prob < ptr->Prob[inTarget][i]){
				//アクションポイント加算「取得回数」
				PTFrame_AddActionPoint(	work, inTarget, i, ADD_TYPE_GET, 1 );
				break;
			}
		}
		GF_ASSERT(i<ENTRY_MAX);
	}
}
